/*
 *  Copyright (C) 2010 {Apertum}Projects. web: www.apertum.ru email: info@apertum.ru
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ru.apertum.qsystem.client.forms;

import java.util.ResourceBundle;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.LayoutStyle;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import lombok.extern.log4j.Log4j2;
import org.jdesktop.application.Application;
import org.jdesktop.application.ResourceMap;
import ru.apertum.qsystem.QSystem;
import ru.apertum.qsystem.client.model.JTreeComboBox;
import ru.apertum.qsystem.common.NetCommander;
import ru.apertum.qsystem.common.exceptions.ClientException;
import ru.apertum.qsystem.common.exceptions.QException;
import ru.apertum.qsystem.common.model.INetProperty;
import ru.apertum.qsystem.server.model.ATreeModel;
import ru.apertum.qsystem.server.model.QService;
import ru.apertum.qsystem.server.model.QServiceTree;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.tree.TreeNode;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.util.LinkedList;

import static ru.apertum.qsystem.server.model.QService.STATUS_FOR_USING;

/**
 * Диалог получения названия услуги для переадресации и сопутствующих параметров. Created on 29 Сентябрь 2008 г., 10:30 Класс диалоговой формы с выбором
 * требуемой услуги из выпадающего списка. Также сдесь можно разместить сопутствующие элементы ввода др. параметров.
 *
 * @author Evgeniy Egorov
 */
@SuppressWarnings({"squid:S3358", "squid:S1192", "squid:S1172", "squid:S1450", "squid:S1604", "squid:S1161", "squid:MaximumInheritanceDepth"})
@Log4j2
public class FRedirect extends JDialog {

    /**
     * Результат.
     */
    private boolean ok;
    /**
     * Используемая ссылка на диалоговое окно.
     */
    private static FRedirect servicesForm;
    private static ResourceMap localeMap = null;

    private static String getLocaleMessage(String key) {
        if (localeMap == null) {
            localeMap = Application.getInstance(QSystem.class).getContext().getResourceMap(FRedirect.class);
        }
        return localeMap.getString(key);
    }

    /**
     * Creates new form FRedirect.
     */
    public FRedirect(INetProperty netProperty, JFrame owner) {
        super(owner, getLocaleMessage("redirect.caption"), true);
        initComponents();
        comboBoxServices = init(netProperty, owner);
    }

    private JTreeComboBox init(INetProperty netProperty, JFrame owner) {

        buttonOk.addActionListener((ActionEvent e) -> {
            ok = true;
            setVisible(false);
        });
        buttonCancel.addActionListener((ActionEvent e) -> {
            ok = false;
            setVisible(false);
        });

        final QService service;
        try {
            service = NetCommander.getServices(netProperty).getRoot();
        } catch (QException e) {
            throw new ClientException("Невозможно получить список предлагаемых услуг. " + e);
        }
        final LinkedList<QService> list = new LinkedList<>();
        QServiceTree.sailToStorm(service, (TreeNode service1) -> {
            final QService ser = (QService) service1;
            if (ser.isRoot() || STATUS_FOR_USING.contains(ser.getStatus())) {
                list.add(ser);
            }
        });
        // дело в том, что из всего дерева услуг надо убрать заглушки и неактивные чтобы в них не перенаправлять.
        // а дерево строится не по указанию на предка, а от корня по дочерним.
        // вот и приходится удалять из дочерних.
        list.stream().forEach(ser -> {
            final LinkedList<QService> del = new LinkedList<>();
            ser.getChildren().stream().filter(che -> (!STATUS_FOR_USING.contains(che.getStatus()))).forEach(del::add);
            del.stream().forEach(ser::remove);
        });

        final JTreeComboBox cbServs = new JTreeComboBox(ServiceTreeModel.build(list)); // это две связанные строчки
        panelTreeCmbx.setLayout(new GridLayout(1, 1));
        panelTreeCmbx.add(cbServs);

        for (QService qService : list) {
            if (qService.isLeaf()) {
                cbServs.setSelectedItem(qService);
                lastSelected = qService;
                break;
            }
        }

        cbServs.addItemListener((ItemEvent e) -> {
            if (((QService) e.getItem()).isLeaf()) {
                lastSelected = (QService) e.getItem();
            } else {
                cbServs.setSelectedItem(lastSelected);
            }
        });

        setLocation((owner.getLocation().x + owner.getWidth() / 2 - getWidth() / 2),
                (owner.getLocation().y + owner.getHeight() / 2 - getHeight() / 2));

        return cbServs;
    }

    final JTreeComboBox comboBoxServices;
    private QService lastSelected = null;

    private static final class ServiceTreeModel extends ATreeModel<QService> {

        private static LinkedList<QService> list;

        @SuppressWarnings("squid:S1319")
        public static ServiceTreeModel build(LinkedList<QService> serviceLinkedList) {
            list = serviceLinkedList;
            return new ServiceTreeModel();
        }

        private ServiceTreeModel() {
            super();
            if (list == null) {
                throw new IllegalStateException("Этот класс можно создать только если поле \"private static LinkedList<QService> list\" не NULL.");
            }
        }

        @Override
        protected LinkedList<QService> load() {
            return list;
        }
    }

    /**
     * Выбор услуги для перенаправления.
     *
     * @param netProperty  свойства коннекта
     * @param owner        относительно этого контрола модальность и позиционирование
     * @param tempComments это если были комменты с прошлых редиректов
     * @param onlyComments показывать или нет что-то другое ктоме вводе комментария
     * @return класс полусения свойств
     */
    public static FRedirect getService(INetProperty netProperty, JFrame owner, String tempComments, boolean onlyComments) {
        log.info("Выбор услуги для перенаправления.");
        if (servicesForm == null) {
            servicesForm = new FRedirect(netProperty, owner);
        }
        servicesForm.setLocation((owner.getLocation().x + owner.getWidth() / 2 - servicesForm.getWidth() / 2),
                (owner.getLocation().y + owner.getHeight() / 2 - servicesForm.getHeight() / 2));
        servicesForm.textAreaTempComments.setText((tempComments == null || tempComments.isEmpty() ? "" : "\n\n__________________________________\n") + tempComments);
        servicesForm.checkBoxBack.setSelected(false);
        servicesForm.checkBoxBack.setVisible(!onlyComments);
        servicesForm.comboBoxServices.setVisible(!onlyComments);
        servicesForm.buttonCancel.setVisible(!onlyComments);
        servicesForm.jLabel1.setVisible(!onlyComments);
        servicesForm.textAreaTempComments.setCaretPosition(0);
        servicesForm.setVisible(true);
        return servicesForm.ok ? servicesForm : null;
    }

    public QService getSelectedService() {
        return (QService) comboBoxServices.getSelectedItem();
    }

    public boolean getRequestBack() {
        return servicesForm.checkBoxBack.isSelected();
    }

    public String getTempComments() {
        return (checkBoxBack.isSelected() ? checkBoxBack.getText() : (checkBoxBack.isVisible() ? "" : getLocaleMessage("redirect.message")))
                + "\n" + textAreaTempComments.getText();
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    // Generated using JFormDesigner non-commercial license
    private void initComponents() {
        ResourceBundle bundle = ResourceBundle.getBundle("ru.apertum.qsystem.client.forms.resources.FRedirect");
        buttonOk = new JButton();
        buttonCancel = new JButton();
        checkBoxBack = new JCheckBox();
        jLabel1 = new JLabel();
        jPanel1 = new JPanel();
        jScrollPane1 = new JScrollPane();
        textAreaTempComments = new JTextArea();
        panelTreeCmbx = new JPanel();

        //======== this ========
        setTitle(bundle.getString("Form.title"));
        setName("Form");
        var contentPane = getContentPane();

        //---- buttonOk ----
        buttonOk.setText(bundle.getString("buttonOk.text"));
        buttonOk.setName("buttonOk");

        //---- buttonCancel ----
        buttonCancel.setText(bundle.getString("buttonCancel.text"));
        buttonCancel.setName("buttonCancel");

        //---- checkBoxBack ----
        checkBoxBack.setText(bundle.getString("checkBoxBack.text"));
        checkBoxBack.setName("checkBoxBack");

        //---- jLabel1 ----
        jLabel1.setText(bundle.getString("jLabel1.text"));
        jLabel1.setName("jLabel1");

        //======== jPanel1 ========
        {
            jPanel1.setBorder(new TitledBorder(bundle.getString("jPanel1.border.title")));
            jPanel1.setName("jPanel1");

            //======== jScrollPane1 ========
            {
                jScrollPane1.setName("jScrollPane1");

                //---- textAreaTempComments ----
                textAreaTempComments.setColumns(20);
                textAreaTempComments.setLineWrap(true);
                textAreaTempComments.setRows(5);
                textAreaTempComments.setWrapStyleWord(true);
                textAreaTempComments.setName("textAreaTempComments");
                jScrollPane1.setViewportView(textAreaTempComments);
            }

            GroupLayout jPanel1Layout = new GroupLayout(jPanel1);
            jPanel1.setLayout(jPanel1Layout);
            jPanel1Layout.setHorizontalGroup(
                jPanel1Layout.createParallelGroup()
                    .addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
            );
            jPanel1Layout.setVerticalGroup(
                jPanel1Layout.createParallelGroup()
                    .addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 113, Short.MAX_VALUE)
            );
        }

        //======== panelTreeCmbx ========
        {
            panelTreeCmbx.setBorder(new EtchedBorder());
            panelTreeCmbx.setName("panelTreeCmbx");

            GroupLayout panelTreeCmbxLayout = new GroupLayout(panelTreeCmbx);
            panelTreeCmbx.setLayout(panelTreeCmbxLayout);
            panelTreeCmbxLayout.setHorizontalGroup(
                panelTreeCmbxLayout.createParallelGroup()
                    .addGap(0, 382, Short.MAX_VALUE)
            );
            panelTreeCmbxLayout.setVerticalGroup(
                panelTreeCmbxLayout.createParallelGroup()
                    .addGap(0, 26, Short.MAX_VALUE)
            );
        }

        GroupLayout contentPaneLayout = new GroupLayout(contentPane);
        contentPane.setLayout(contentPaneLayout);
        contentPaneLayout.setHorizontalGroup(
            contentPaneLayout.createParallelGroup()
                .addGroup(contentPaneLayout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(contentPaneLayout.createParallelGroup()
                        .addComponent(jLabel1)
                        .addGroup(GroupLayout.Alignment.TRAILING, contentPaneLayout.createSequentialGroup()
                            .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                                .addComponent(panelTreeCmbx, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(checkBoxBack, GroupLayout.Alignment.LEADING)
                                .addGroup(contentPaneLayout.createSequentialGroup()
                                    .addComponent(buttonOk)
                                    .addGap(18, 18, 18)
                                    .addComponent(buttonCancel, GroupLayout.PREFERRED_SIZE, 89, GroupLayout.PREFERRED_SIZE))
                                .addComponent(jPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                            .addContainerGap())))
        );
        contentPaneLayout.setVerticalGroup(
            contentPaneLayout.createParallelGroup()
                .addGroup(contentPaneLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jLabel1)
                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(panelTreeCmbx, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(jPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(contentPaneLayout.createParallelGroup()
                        .addGroup(contentPaneLayout.createSequentialGroup()
                            .addGap(32, 32, 32)
                            .addGroup(contentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                .addComponent(buttonOk)
                                .addComponent(buttonCancel)))
                        .addGroup(contentPaneLayout.createSequentialGroup()
                            .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
                            .addComponent(checkBoxBack)))
                    .addContainerGap())
        );
        pack();
        setLocationRelativeTo(getOwner());
    }// </editor-fold>//GEN-END:initComponents

    // Variables declaration - do not modify//GEN-BEGIN:variables
    // Generated using JFormDesigner non-commercial license
    private JButton buttonOk;
    private JButton buttonCancel;
    private JCheckBox checkBoxBack;
    private JLabel jLabel1;
    private JPanel jPanel1;
    private JScrollPane jScrollPane1;
    private JTextArea textAreaTempComments;
    private JPanel panelTreeCmbx;
    // End of variables declaration//GEN-END:variables
}
